package com.anlogic.sdk.bsp.settings;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Table;

import com.anlogic.sdk.tools.model.LibraryInfo;

public class LibraryView {
	BspSettingsView parentView;

	private IBspSettingTool bspSettingTool;

	private Composite content;

	private CheckboxTableViewer librariesViewer;

	private TableViewerColumn[] librariesViewerColumn;

	private List<Component> libraries = new ArrayList<Component>();

	private String[] libraryHeaders = new String[] { "", "Name", "Version", "Description" };

	private int[] libraryHeaderWidths = new int[] { 50, 200, 100, 300 };

	public LibraryView(BspSettingsView parentView, Composite parent, IBspSettingTool bspSettingTool) {
		this.parentView = parentView;
		this.bspSettingTool = bspSettingTool;
		this.createContentArea(parent);
	}

	public Composite getContent() {
		return this.content;
	}

	public Display getDisplay() {
		return this.content.getDisplay();
	}
	
	public void refreshLibraries(Object input) {
		this.librariesViewer.setInput(input);
		this.librariesViewer.refresh();
	}

	public CheckboxTableViewer getLibrariesViewer() {
		return this.librariesViewer;
	}

	public void addCheckStateListener(ICheckStateListener l) {
		this.librariesViewer.addCheckStateListener(l);
	}

	public void setVersionEditingSupport(EditingSupport es) {
		TableViewerColumn vc = this.librariesViewerColumn[2];
		vc.setEditingSupport(es);
	}

	public void setLibrariesContentProvider(IStructuredContentProvider p) {
		this.librariesViewer.setContentProvider((IContentProvider) p);
	}

	public void setLibrariesLabelProvider(ITableLabelProvider p) {
		this.librariesViewer.setLabelProvider((IBaseLabelProvider) p);
	}
	
	public void createContentArea(Composite parent) {
		this.content = new Composite(parent, SWT.NONE);
		this.content.setLayout((Layout) new GridLayout(1, false));
		this.content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		
		createLibraryView(this.content);
	}
	
	private void createLibraryView(Composite parent) {
		Label info = new Label(parent, SWT.WRAP);
		info.setText("Check the box next to the libraries you want included in your Board Support Package.You can configure the library in the navigator on the left.");
		this.librariesViewer = CheckboxTableViewer.newCheckList(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.CHECK);
		this.librariesViewer.setUseHashlookup(true);
		this.librariesViewerColumn = new TableViewerColumn[this.libraryHeaders.length];
		for (int i = 0; i < this.libraryHeaders.length; i++) {
			this.librariesViewerColumn[i] = new TableViewerColumn((TableViewer) this.librariesViewer, 4);
			this.librariesViewerColumn[i].getColumn().setText(this.libraryHeaders[i]);
			this.librariesViewerColumn[i].getColumn().setWidth(this.libraryHeaderWidths[i]);
			this.librariesViewerColumn[i].getColumn().setResizable(true);
			this.librariesViewerColumn[i].getColumn().setMoveable(false);
		}
		Table table = this.librariesViewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		table.setLayout((Layout) new GridLayout(1, false));
		GridData td = new GridData(SWT.FILL, SWT.TOP, true, true);
		td.verticalIndent = 15;
		td.horizontalIndent = 5;
		table.setLayoutData(td);
	}
	
	public void viewReady() {
		createLibrariesList();

		LibraryVersionEditingSupport editor = new LibraryVersionEditingSupport(
				(ColumnViewer) this.getLibrariesViewer());
		this.setVersionEditingSupport(editor);
		LibrariesManager libman = new LibrariesManager();
		this.setLibrariesContentProvider(libman);
		this.setLibrariesLabelProvider(libman);
		this.refreshLibraries(libman);
		setCheckStateForLibraries();
		this.addCheckStateListener(libman);
	}

	private void setCheckStateForLibraries() {
		CheckboxTableViewer viewer = this.getLibrariesViewer();
		Iterator<Component> itr = this.libraries.iterator();
		while (itr.hasNext()) {
			Component l = itr.next();
			if (l.isEnabled())
				viewer.setChecked(l, true);
		}
	}

	private void createLibrariesList() {
		Map<String, LibraryInfo> libInsts = this.bspSettingTool.getBspLibInfo();
		String[] libList = this.bspSettingTool.getLibraryNames();
		for (String lib : libList) {
			Component libComp = findLibrary(lib);
			if (libComp == null) {
				String[] versions = this.bspSettingTool.getLibraryVersions(lib);
				String[] descriptions = this.bspSettingTool.getLibDescs(lib);
				libComp = new Component();
				libComp.setName(lib);
				libComp.addVersions(versions);
				libComp.addDescriptions(descriptions);
				libComp.setSelectedVersion(versions[versions.length - 1]);
				this.libraries.add(libComp);
			}
			if (libInsts.containsKey(lib)) {
				libComp.setEnabled(true);
				if (this.bspSettingTool.isConfigurable(lib)) {
					this.parentView.addLibraryChild(lib);
				}
			}
		}
	}

	public void libraryAdded(String lib, String ver) {
		this.bspSettingTool.addLibrary(lib, ver);
		if (this.bspSettingTool.isConfigurable(lib)) {
			this.parentView.addLibraryChild(lib);
		}
	}

	public void libraryRemoved(String lib) {
		this.bspSettingTool.removeLibrary(lib);
		if (this.bspSettingTool.isConfigurable(lib)) {
			this.parentView.removeLibraryChild(lib);
		}
	}

	private Component findLibrary(String name) {
		if (this.libraries.isEmpty())
			return null;
		Iterator<Component> itr = this.libraries.iterator();
		while (itr.hasNext()) {
			Component l = itr.next();
			if (l.getName().equals(name))
				return l;
		}
		return null;
	}

	class LibrariesManager extends LabelProvider
			implements IStructuredContentProvider, ITableLabelProvider, ICheckStateListener {
		public Object[] getElements(Object inputElement) {
			return libraries.toArray();
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		public String getColumnText(Object element, int columnIndex) {
			if (!(element instanceof Component))
				return "";
			Component l = (Component) element;
			switch (columnIndex) {
			case 1:
				return l.getName();
			case 2:
				return l.getVersions().get(l.getSelectedVersion());
			case 3:
				return l.getDescriptions().get(l.getSelectedVersion());
			}
			return "";
		}

		public void checkStateChanged(CheckStateChangedEvent event) {
			Object o = event.getElement();
			if (!(o instanceof Component))
				return;
			Component l = (Component) o;
			l.setEnabled(event.getChecked());
			if (l.isEnabled()) {
				libraryAdded(l.getName(), l.getVersions().get(l.getSelectedVersion()));
			} else {
				libraryRemoved(l.getName());
			}
		}
	}

	class LibraryVersionEditingSupport extends EditingSupport {
		private ComboBoxCellEditor[] cellEditors;

		private ColumnViewer viewer;

		public LibraryVersionEditingSupport(ColumnViewer viewer) {
			super(viewer);
			TableViewer tv = (TableViewer) viewer;
			Table t = tv.getTable();
			this.cellEditors = new ComboBoxCellEditor[libraries.size()];
			for (int i = 0; i < this.cellEditors.length; i++)
				this.cellEditors[i] = new ComboBoxCellEditor((Composite) t,
						((Component) libraries.get(i)).getVersions().<String>toArray(new String[0]), 8);
			this.viewer = viewer;
		}

		protected boolean canEdit(Object element) {
			return true;
		}

		protected CellEditor getCellEditor(Object element) {
			if (!(element instanceof Component))
				return null;
			Component l = (Component) element;
			int index = libraries.indexOf(l);
			if (index == -1)
				return null;
			return (CellEditor) this.cellEditors[index];
		}

		protected Object getValue(Object element) {
			if (!(element instanceof Component))
				return null;
			Component l = (Component) element;
			return l.getSelectedVersion();
		}

		protected void setValue(Object element, Object value) {
			if (!(element instanceof Component))
				return;
			Component l = (Component) element;
			Integer i = (Integer) value;
			if (l.getSelectedVersion() != i.intValue()) {
				l.setSelectedVersion(i.intValue());
				String version = l.getVersions().get(l.getSelectedVersion());
				bspSettingTool.setLibVersion(l.getName(), version);
			}
			this.viewer.refresh(l);
		}
	}
}
